﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Web.Script.Serialization;
using Admintool.ExtensionMethods;
using Admintool.Infrastructure;
using Newtonsoft.Json.Linq;
using RestSharp;

namespace Admintool
{
    partial class Program
    {
        [Command("\texport userinfo by input uid list from file")]
        public static void ExportUserInfo([Required(Description = "uid file path")]string uidFile,
            [Optional(@"d:\result.txt", new string[] { "o" }, Description = "output file")] string outputFile
            , [Optional("localhost", new string[] { "h" }, Description = "host name or ip")]string host
             , [Optional(9996, new string[] { "p" }, Description = "port number")]int port
            , [Optional("uid,ualias,umobphone,umail", new string[] { "f" }, Description = "port number")]string fields)
        {

            if (!File.Exists(uidFile))
            {
                ConsoleHelper.ShowMessage("{0} does not exist!", ConsoleColor.Red, uidFile);
                return;
            }

            // http://172.16.58.97:9996/web/getuserfromcache
            using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite))
            {
                int index = 1;
                StringBuilder sb = new StringBuilder();
                string raw = string.Empty;
                IEnumerableExtension.ReadFromFile(uidFile).ForEach((string line) => {
                    var client = new RestClient(string.Format("http://{0}:{1}", host, port));
                    var request = new RestRequest("web/getuserfromcache", Method.POST);
                    request.RequestFormat = DataFormat.Json;
                    request.AddBody(new Dictionary<string, object>
                    {
                        {"uid",line},
                        {"keyType",0}
                    });

                    RestResponse response = client.Execute(request) as RestResponse;
                    if (response.StatusCode == HttpStatusCode.OK && response.ErrorException == null)
                    {
                        JObject jo = JObject.Parse(response.Content);
                        if (jo != null)
                        {
                            JToken jt = jo["GetUserFromCacheResult"];
                            raw = jt.ToString();
                            if (jt.HasValues && jt != null)
                            {
                                //uid, alias,phone,mail
                                foreach (var field in fields.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                                {
                                    sb.Append(jt[field] ?? string.Empty).Append("\t");
                                }
                                sb.Append(Environment.NewLine);
                            }
                        }

                    }
                    ConsoleHelper.ShowMessage(string.Format("[{0} uid# {1}]:{2} ,raw: {3}", index++, line, response.StatusCode, raw), ConsoleColor.Green);

                });  //end if each
                var bytes = Encoding.UTF8.GetBytes(sb.ToString().Trim());
                fs.Write(bytes, 0, bytes.Length);
                fs.Close();
            }
        }



        [Command("\tget cache userinfo for uid")]
        public static void GetUserFromCache(
            [Required(Description = "uid")]string uid
            , [Optional("localhost", new string[] { "h" }, Description = "host name or ip")]string host
             , [Optional(9996, new string[] { "p" }, Description = "port number")]int port
             )
        {
            //172.16.58.99

            Uri mexAddress = new Uri(string.Format(@"http://{0}:{1}/?wsdl", host, port));
            MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.HttpGet;
            string contractName = "IManageService";
            string operationName = "GetUserFromCache";
            object[] operationParameters = new object[] { uid, 0 };

            // Get the metadata file from the service.
            MetadataExchangeClient mexClient = new MetadataExchangeClient(mexAddress, mexMode);
            mexClient.ResolveMetadataReferences = true;
            MetadataSet metaSet = mexClient.GetMetadata();

            // Import all contracts and endpoints
            WsdlImporter importer = new WsdlImporter(metaSet);
            Collection<ContractDescription> contracts = importer.ImportAllContracts();
            ServiceEndpointCollection allEndpoints = importer.ImportAllEndpoints();

            // Generate type information for each contract
            ServiceContractGenerator generator = new ServiceContractGenerator();
            var endpointsForContracts = new Dictionary<string, IEnumerable<ServiceEndpoint>>();

            foreach (ContractDescription contract in contracts)
            {
                generator.GenerateServiceContractType(contract);
                // Keep a list of each contract's endpoints
                endpointsForContracts[contract.Name] = allEndpoints.Where(
                    se => se.Contract.Name == contract.Name).ToList();
            }

            if (generator.Errors.Count != 0)
                throw new Exception("There were errors during code compilation.");


            // Generate a code file for the contracts 
            CodeGeneratorOptions options = new CodeGeneratorOptions();
            options.BracingStyle = "C";
            CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#");

            // Compile the code file to an in-memory assembly
            // Don't forget to add all WCF-related assemblies as references
            CompilerParameters compilerParameters = new CompilerParameters(
                new string[] { "System.dll", "System.ServiceModel.dll", "System.Runtime.Serialization.dll" });
            compilerParameters.GenerateInMemory = true;

            CompilerResults results = codeDomProvider.CompileAssemblyFromDom(
                compilerParameters, generator.TargetCompileUnit);

            if (results.Errors.Count > 0)
            {
                throw new Exception("There were errors during  generated code compilation");
            }
            else
            {
                // Find the proxy type that was generated for the specified contract
                // (identified by a class that implements 
                // the contract and ICommunicationbject)
                Type clientProxyType = results.CompiledAssembly.GetTypes().First(
                    t => t.IsClass &&
                        t.GetInterface(contractName) != null &&
                        t.GetInterface(typeof(ICommunicationObject).Name) != null);

                Type clientReturnType = clientProxyType.GetMethod(operationName).ReturnType;

                // Get the first service endpoint for the contract
                ServiceEndpoint se = endpointsForContracts[contractName].First();

                // Create an instance of the proxy
                // Pass the endpoint's binding and address as parameters
                // to the ctor
                object instance = results.CompiledAssembly.CreateInstance(
                    clientProxyType.Name,
                    false,
                    System.Reflection.BindingFlags.CreateInstance,
                    null,
                    new object[] { se.Binding, se.Address },
                    CultureInfo.CurrentCulture, null);

                // Get the operation's method, invoke it, and get the return value
                object retVal = instance.GetType().GetMethod(operationName).
                    Invoke(instance, operationParameters);

                string json = new JavaScriptSerializer().Serialize(retVal);

                Console.WriteLine(json);
            }



        }
    }

}
